今天就緊接著把最後一個設計模式 - 狀態模式 給介紹完吧!
狀態模式是一種行為設計模式,讓我們在一個物件的內部狀態變化時改變其行為,使其看上去就像改變了自身所屬的類別一樣
有個簡單的例子,像是我們在部落格之類的網站上發表文章,文章發送前的狀態可能是 草稿、審核中以及已發佈等等的狀態,這種模擬就可以用狀態模式實現
下面就用文章的例子來看看,假設三種狀態 草稿 可以編輯,確認後轉 審核中 審核過了後轉 已發佈
class Document;
class State
{
protected:
    Document* doc_;
public:
    void set_doc(Document* doc)
    {
        this->doc_ = doc;
    }
    virtual void Change() = 0;
    virtual void Check() = 0;
    virtual void Confirm() = 0;
};
class DraftState : public State {
public:
    void Change() override;
    void Check() override;
    void Confirm() override;
};
class ReviewState : public State {
public:
    void Change() override;
    void Check() override;
    void Confirm() override;
};
class Document
{
private:
    State* state_;
public:
    Document()
    {
        this->Transition(new DraftState);
    }
    void Transition(State* state)
    {
        if (this->state_ != nullptr)
        {
            delete this->state_;
        }
        this->state_ = state;
        this->state_->set_doc(this);
    }
    void Review()
    {
        this->state_->Check();
    }
    void Write()
    {
        this->state_->Change();
    }
    void Confirm()
    {
        this->state_->Confirm();
    }
};
class PublishState : public State {
public:
    void Change() override
    {
        cout << "Publish no change " << endl;
    }
    void Check() override
    {
        cout << "Publish no check " << endl;
    }
    void Confirm() override
    {
        cout << "Doc is publish " << endl;
    }
};
void DraftState::Change()
{
    cout << "Draft can change " << endl;
}
void DraftState::Check()
{
    cout << "Draft to check " << endl;
    this->doc_->Transition(new ReviewState);
}
void DraftState::Confirm()
{
    cout << "Draft no confirm " << endl;
}
void ReviewState::Change()
{
    cout << "Review no change " << endl;
}
void ReviewState::Check()
{
    cout << "Review no check " << endl;
}
void ReviewState::Confirm()
{
    cout << "Review to confirm " << endl;
    this->doc_->Transition(new PublishState);
}
int main() {
    Document* doc = new Document;
    doc->Write();
    doc->Review();
    doc->Confirm();
    return 0;
}
可以看到狀態模式能定義出各種狀態該做的事情在不同類別中,但代價是更多更複雜的程式碼,如果狀態很少或是很少改變狀態就可以不用考慮狀態模式唷!
今天就將設計模式之前欠的部分補齊囉~期待完賽 XD